﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Web;
using System.Web.Configuration;

#pragma warning disable 618

namespace Core
{
	public class SqlServerMessageStorage : IMessageStorage
	{
		String m_ConnectionString = "";
		Int64 m_MaxKey = 1;
        DateTime m_MaxCreatedTime = DateTime.Now;

		public SqlServerMessageStorage()
		{
			Configuration config = WebConfigurationManager.OpenWebConfiguration(
				HttpContext.Current.Request.ApplicationPath == "/" ? "/Lesktop" : HttpContext.Current.Request.ApplicationPath + "/Lesktop"
			);

			m_ConnectionString = config.ConnectionStrings.ConnectionStrings["Lesktop_ConnectString"].ConnectionString;

			SqlConnection conn = new SqlConnection(ConnectionString);
			conn.Open();
			try
			{
				SqlCommand cmd = new SqlCommand(
					"select max([Key]) as MaxKey, max(CreatedTime) as MaxCreatedTime from Message",
					conn
				);

				SqlDataReader reader = cmd.ExecuteReader();
				if (reader.Read())
				{
					m_MaxKey = reader[0] == DBNull.Value ? 1 : Convert.ToInt64(reader[0]);
					m_MaxCreatedTime = reader[1] == DBNull.Value ? DateTime.Now : Convert.ToDateTime(reader[1]);
				}
			}
			finally
			{
				conn.Close();
			}
		}

		private string ConnectionString
		{
			get
			{
				return m_ConnectionString;
			}
		}

		Int64 IMessageStorage.GetMaxKey()
		{
			return m_MaxKey;
		}

		DateTime IMessageStorage.GetCreatedTime()
		{
			return m_MaxCreatedTime;
		}

		List<Message> IMessageStorage.FindHistory(long user, long peer, DateTime from, DateTime to)
		{
			SqlConnection conn = new SqlConnection(ConnectionString);
			conn.Open();
			try
			{

				if (from == null) from = new DateTime(2000, 1, 1);
				SqlCommand cmd = new SqlCommand("FindHistory", conn);
				cmd.CommandType = CommandType.StoredProcedure;

				cmd.Parameters.Add("user", DbType.Int64).Value = user;
				cmd.Parameters.Add("peer", DbType.Int64).Value = peer;
				cmd.Parameters.Add("from", DbType.DateTime).Value = from;
				cmd.Parameters.Add("to", DbType.DateTime).Value = to;

				List<Message> messages = new List<Message>();
				SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleResult);
				try
				{
					while (reader.Read())
					{
						Message msg = new Message(
							AccountImpl.Instance.GetUserInfo(Convert.ToInt64(reader[2])),
							AccountImpl.Instance.GetUserInfo(Convert.ToInt64(reader[1])),
							reader.GetString(3), Convert.ToDateTime(reader[4]), Convert.ToInt64(reader[0])
						);
						messages.Add(msg);
					}
				}
				finally
				{
					reader.Close();
				}
				return messages;
			}
			finally
			{
				conn.Close();
			}
		}

		List<Message> IMessageStorage.Find(long receiver, long sender, Nullable<DateTime> from)
		{
			SqlConnection conn = new SqlConnection(ConnectionString);
			conn.Open();
			try
			{

				if (from == null) from = new DateTime(2000, 1, 1);
				SqlCommand cmd = new SqlCommand("FindMessages", conn);
				cmd.CommandType = CommandType.StoredProcedure;
				cmd.Parameters.Add("user", DbType.Int32).Value = receiver;
				cmd.Parameters.Add("peer", DbType.Int32).Value = sender;
				cmd.Parameters.Add("from", DbType.DateTime).Value = from.Value;

				List<Message> messages = new List<Message>();
				SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleResult);
				try
				{
					while (reader.Read())
					{
						Message msg = new Message(
							AccountImpl.Instance.GetUserInfo(Convert.ToInt64(reader[2])),
							AccountImpl.Instance.GetUserInfo(Convert.ToInt64(reader[1])),
							reader.GetString(3), Convert.ToDateTime(reader[4]), Convert.ToInt64(reader[0])
						);
						messages.Add(msg);
					}
				}
				finally
				{
					reader.Close();
				}
				return messages;
			}
			finally
			{
				conn.Close();
			}
		}

		void IMessageStorage.Write(List<Message> messages)
		{
			SqlConnection conn = new SqlConnection(ConnectionString);
			conn.Open();
			try
			{
				//启动事务
				SqlTransaction trans = conn.BeginTransaction();

				try
				{
					foreach (Message msg in messages)
					{
						//超过缓存的最大值，将缓存中的消息全部写入数据库
						SqlCommand cmd = new SqlCommand(
							"insert into Message (Receiver,Sender,Content,CreatedTime,[Key]) values (@Receiver,@Sender,@Content,@CreatedTime,@Key)",
							conn
						);
						cmd.Parameters.Add("Receiver", DbType.Int32).Value = msg.Receiver.ID;
						cmd.Parameters.Add("Sender", DbType.Int32).Value = msg.Sender.ID;
						cmd.Parameters.Add("Content", DbType.String).Value = msg.Content;
						cmd.Parameters.Add("CreatedTime", DbType.DateTime).Value = msg.CreatedTime;
						cmd.Parameters.Add("Key", DbType.Int64).Value = msg.Key;
						cmd.Transaction = trans;
						cmd.ExecuteNonQuery();
					}

					trans.Commit();
				}
				catch
				{
					trans.Rollback();
				}
			}
			finally
			{
				conn.Close();
			}
		}
	}
}

#pragma warning restore 618